import { writable, readable, derived, get as getVal } from "svelte/store";
import { differenceInSeconds } from "date-fns";
import { AlertType, type AlertItem } from "@component/alerts/conf";
import { defaultStsCredential } from "./entity/cos/StsCredential";
import { getStsCredential } from "@api/cos";

export const iif = <T>(condition: boolean, true_val: T, false_val: T) => {
  return condition ? true_val : false_val;
};

export const isLoading$ = writable(false);
export const loadingText$ = writable("");
let loadingTimeoutId: number;

export const closeSpinner = () => {
  if (getVal(isLoading$)) {
    isLoading$.set(false);
    loadingText$.set("");
    if (loadingTimeoutId) {
      clearTimeout(loadingTimeoutId);
    }
  }
};

export const openSpinner = (text = "", timeout = -1) => {
  if (!getVal(isLoading$)) {
    isLoading$.set(true);
    loadingText$.set(text);
    if (timeout >= 0) {
      loadingTimeoutId = setTimeout(() => {
        closeSpinner();
        alertError("任务超时!");
      }, timeout);
    }
  }
};

const alertItems$ = writable<AlertItem[]>([]);

export const alerts$ = derived(
  alertItems$,
  ($alertItems$, set: (values: AlertItem[]) => void) => set($alertItems$)
);

let _removeExpiredAlertInterval: number;

export const alert = (message: string, type: AlertType) => {
  alertItems$.update((v) => [...v, { type, message, added_at: new Date() }]);
  if (!_removeExpiredAlertInterval) {
    _removeExpiredAlertInterval = setInterval(() => {
      console.log("timer exec...");
      let arr = getVal(alertItems$);
      if (arr.length > 0) {
        console.log("alerts$2 in interval:", arr);
        let now = new Date();
        let remains = arr.filter(
          (v) => differenceInSeconds(now, v.added_at) < 5
        );
        alertItems$.set(remains);
      } else {
        clearInterval(_removeExpiredAlertInterval);
        _removeExpiredAlertInterval = null;
      }
    }, 1000);
  }
};

export const closeAlert = (idx: number) => {
  if (idx !== -1) {
    let arr = getVal(alertItems$);
    if (arr.length > 0) {
      arr.splice(idx, 1);
      alertItems$.set(arr);
    }
  }
};

export const alertError = (message: string) => {
  return alert(message, AlertType.Error);
};

export const alertInfo = (message: string) => {
  return alert(message, AlertType.Info);
};

const createNextTimeoutFunc = (ts: number, fn: () => void) => {
  return setTimeout(fn, ts);
};

export const stsCredential$ = readable(
  defaultStsCredential,
  function start(set) {
    let fn = () => {
      getStsCredential().then((v) => {
        set(v);
        const nextExecAt = v.expired_time * 1000 - +new Date();
        console.log("next ts to exec at:", nextExecAt);
        createNextTimeoutFunc(nextExecAt, fn);
      });
    };
    createNextTimeoutFunc(0, fn);
  }
);
